/**
 * $version:  0.1 
 * $Date: 2012-03-19 
 *
 * Copyright (C) 2010-2011 Jawa Software. All rights reserved.
 *
 */

package org.jawa.core.container;

import java.io.File;
import java.io.FilenameFilter;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;

import org.jawa.core.JawaServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 负责装载插件的classes,database,i18n,web,lib等目录下的class或者是资源。
 * 该类将搜索<tt>plugin</tt>目录中的classes和JAR文件，然后根据搜索的资源构造类加载器
 * and JAR files, then constructs a class loader for the resources found.
 * 资源加载如下:<ul>
 * <p/>
 * <li>所有 <tt>lib</tt>目录下的JAR文件将添加到 classpath中.
 * <li>所有<tt>classes</tt>文件将添加到 classpath中.
 * </ul>
 *
 * @author JAWA
 */
public class PluginClassLoader extends URLClassLoader {

	private static final Logger Log = LoggerFactory.getLogger(PluginClassLoader.class);

    public PluginClassLoader() {
        super(new URL[] {}, findParentClassLoader());
    }

    /**
     * 类加载器中添加一个目录.
     *
     * @param directory 要添加的目录.
     * @param developmentMode　如果<tt>plugin</tt>在开发模式下运行时该值为true . 
     * 解决部署插件<tt>plugin</tt>和开发相关类时的冲突
     */
    public void addDirectory(File directory, boolean developmentMode) {
        try {
            // 将一个目录添加到classpath中
            File classesDir = new File(directory, "classes");
            if (classesDir.exists()) {
                addURL(classesDir.toURI().toURL());
            }

            // 添加 database 目录到 classpath.
            File databaseDir = new File(directory, "database");
            if(databaseDir.exists()){
                addURL(databaseDir.toURI().toURL());
            }

            // 添加 i18n 目录到 classpath.
            File i18nDir = new File(directory, "i18n");
            if(i18nDir.exists()){
                addURL(i18nDir.toURI().toURL());
            }

            // 添加  web 目录到 classpath.
            File webDir = new File(directory, "web");
            if(webDir.exists()){
                addURL(webDir.toURI().toURL());
            }

            // 添加 lib 目录到 classpath.
            File libDir = new File(directory, "lib");
            File[] jars = libDir.listFiles(new FilenameFilter() {
                public boolean accept(File dir, String name) {
                    return name.endsWith(".jar") || name.endsWith(".zip");
                }
            });
            if (jars != null) {
                for (int i = 0; i < jars.length; i++) {
                    if (jars[i] != null && jars[i].isFile()) {
                        if (developmentMode) {
                            // 不要将plugin-pluginName.jar添加到CLASSPATH中.
                            if (!jars[i].getName().equals("plugin-" + directory.getName() + ".jar")) {
                                addURL(jars[i].toURI().toURL());
                            }
                        }
                        else {
                            addURL(jars[i].toURI().toURL());
                        }
                    }
                }
            }
        }
        catch (MalformedURLException mue) {
            Log.error(mue.getMessage(), mue);
        }
    }

    public void addURLFile(URL file) {
        addURL(file);
    }

    /**
     * 根据上下文找出最佳的父类加载器.
     *
     * @return 返回最佳加载器供使用.
     */
    private static ClassLoader findParentClassLoader() {
        ClassLoader parent = JawaServer.class.getClassLoader();
        if (parent == null) {
            parent = PluginClassLoader.class.getClassLoader();
        }
        if (parent == null) {
            parent = ClassLoader.getSystemClassLoader();
        }
        return parent;
    }
}
